#include "PreCompile.hpp"
#include "UtilsTests.hpp"
#include "../Utils.hpp"

namespace BuildNG
{
  void UtilsTests::test_int_to_str()
  {
    assert(int_to_str(0) == "0");
    assert(int_to_str(100) == "100");
    assert(int_to_str(-100) == "-100");
    assert(int_to_str(2147483647) == "2147483647");
    assert(int_to_str(-2147483647) == "-2147483647");
    assert(int_to_str(-2147483647 - 1) == "-2147483648");
  }

  void UtilsTests::test_try_parse_int()
  {
    gint32 value;
    TryParseIntRes res;

    res = try_parse_int("0",value);
    assert(res == TryParseIntRes_Success);
    assert(value == 0);

    res = try_parse_int("-0",value);
    assert(res == TryParseIntRes_Success);
    assert(value == 0);

    res = try_parse_int("1",value);
    assert(res == TryParseIntRes_Success);
    assert(value == 1);

    res = try_parse_int("1337",value);
    assert(res == TryParseIntRes_Success);
    assert(value == 1337);

    res = try_parse_int("-1337",value);
    assert(res == TryParseIntRes_Success);
    assert(value == -1337);

    res = try_parse_int("   -1337  ",value);
    assert(res == TryParseIntRes_Success);
    assert(value == -1337);

    res = try_parse_int("   - 1337  ",value);
    assert(res == TryParseIntRes_ParseError);

    res = try_parse_int("   133t  ",value);
    assert(res == TryParseIntRes_ParseError);

    res = try_parse_int("   --1337  ",value);
    assert(res == TryParseIntRes_ParseError);

    res = try_parse_int("2147483648",value);
    assert(res == TryParseIntRes_OutOfRange);

    res = try_parse_int("-2147483648",value);
    assert(res == TryParseIntRes_Success);
    assert(value == -2147483647 - 1);

    res = try_parse_int("2147483647",value);
    assert(res == TryParseIntRes_Success);
    assert(value == 2147483647);

    res = try_parse_int("-2147483647",value);
    assert(res == TryParseIntRes_Success);
    assert(value == -2147483647);

    res = try_parse_int("-2147483647000",value);
    assert(res == TryParseIntRes_OutOfRange);

    res = try_parse_int("",value);
    assert(res == TryParseIntRes_ParseError);

    res = try_parse_int("       ",value);
    assert(res == TryParseIntRes_ParseError);
  }

  void UtilsTests::test_parse_command_line_args()
  {
    std::vector<Glib::ustring> args;

    args = shell_parse_windows_style("param1 number2\targ3 \t and    last_one");
    assert(args.size() == 5);
    assert(args[0] == "param1");
    assert(args[1] == "number2");
    assert(args[2] == "arg3");
    assert(args[3] == "and");
    assert(args[4] == "last_one");

    args = shell_parse_windows_style("");
    assert(args.size() == 0);

    args = shell_parse_windows_style("  \t  ");
    assert(args.size() == 0);

    args = shell_parse_windows_style("   laaa   ");
    assert(args.size() == 1);
    assert(args[0] == "laaa");

    args = shell_parse_windows_style("foo\\\\\\\\bar");
    assert(args.size() == 1);
    assert(args[0] == "foo\\\\\\\\bar");

    args = shell_parse_windows_style("foo\\\\\\\\\"b a r\"");
    assert(args.size() == 1);
    assert(args[0] == "foo\\\\b a r");

    args = shell_parse_windows_style("foo\\\\\\\" laa");
    assert(args.size() == 2);
    assert(args[0] == "foo\\\"");
    assert(args[1] == "laa");
  }

  void UtilsTests::test_compare_string_begin()
  {
    const gchar *str = "foo bar";
    assert(compare_string_begin(str,str + strlen(str),"foo") == true);
    assert(compare_string_begin(str,str + strlen(str),"foo bar") == true);
    assert(compare_string_begin(str,str + strlen(str),"foo barbar") == false);
    assert(compare_string_begin(str,str + strlen(str),"foobar") == false);
    assert(compare_string_begin(str,str + strlen(str),"") == true);
    assert(compare_string_begin(str,str + strlen(str),"  foo bar") == false);
  }

  static Glib::ustring trim_wrapped(const Glib::ustring &in)
  {
    Glib::ustring ret = in;
    trim(ret);
    return ret;
  }

  void UtilsTests::test_trim()
  {
    assert(trim_wrapped("") == "");
    assert(trim_wrapped("foobar") == "foobar");
    assert(trim_wrapped("      ") == "");
    assert(trim_wrapped("foo  bar") == "foo  bar");
    assert(trim_wrapped("   foo  bar") == "foo  bar");
    assert(trim_wrapped("foo  bar   ") == "foo  bar");
    assert(trim_wrapped("     foo  bar  ") == "foo  bar");
    assert(trim_wrapped("  \t   foo  bar\t  ") == "foo  bar");
    assert(trim_wrapped(" ei p\xc3\xb8lse med br\xc3\xb8""d   ") == "ei p\xc3\xb8lse med br\xc3\xb8""d");
  }

  void UtilsTests::test_get_next_pow2()
  {
    int prev = 0;
    for(int i = 0;i < 32;i++)
    {
      assert(get_next_pow2((guint32)1 << i) == ((guint32)1 << i));

      if(i < 11)
      {
        guint32 cur = (guint32)1 << i;
        for(guint32 j = prev + 1;j <= cur;j++)
        {
          assert(get_next_pow2(j) == cur);
        }
        prev = cur;
      }
    }

    //assert(get_next_pow2(0xf0000000) == 0);   // overflows
    assert(get_next_pow2(0x80000000) == 0x80000000);
  }

  void UtilsTests::test_get_next_pow2_size_t()
  {
    int prev = 0;
    for(int i = 0;i < sizeof(size_t) * 8;i++)
    {
      assert(get_next_pow2_size_t((size_t)1 << i) == ((size_t)1 << i));

      if(i < 11)
      {
        guint32 cur = (guint32)1 << i;
        for(guint32 j = prev + 1;j <= cur;j++)
        {
          assert(get_next_pow2(j) == cur);
        }
        prev = cur;
      }
    }

    //assert(get_next_pow2(0xf0000000) == 0);   // overflows
    assert(get_next_pow2(0x80000000) == 0x80000000);
  }
}

